package com.yanqu.road.server.manger.config;

import com.yanqu.road.dao.impl.config.ChildDaoImpl;
import com.yanqu.road.entity.child.ChildGrowStageAddition;
import com.yanqu.road.entity.config.children.*;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.logic.bussiness.config.ChildBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.enums.eSexType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.language.LanguageType;
import com.yanqu.road.entity.player.UserChildSite;
import com.yanqu.road.entity.servercenter.TitleInfo;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.charitable.CharitableModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.CardModule;
import com.yanqu.road.server.gameplayer.module.player.HouseModule;
import com.yanqu.road.server.logic.calc.CalculationManager;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChildMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(ChildMgr.class.getName());

    private static RandomHelper threadRandom = new RandomHelper();

    private static Map<Integer, ChildTalentInfo> childTalentInfoMap;

    private static int minChildTalent;

    private static int minChildTrainType;

    private static Map<String, List<String>> menNameMap;

    private static Map<String, List<String>> womenNameMap;

    private static Map<Integer, ChildOccupation> childOccupationMap;

    private static Map<Integer, List<ChildOccupation>> childOccupationTypeMap;

    private static Map<Integer, ChildTrainInfo> childTrainInfoMap;

    private static List<ChildTrainInfo> childTrainInfoList;

    private static List<ChildAppearance> childAppearanceList;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean reloadConfig() {
        childTalentInfoMap = ChildBussiness.getChildTalentInfoMap();
        if(childTalentInfoMap.size() < 1){
            return false;
        }
        initMinTalent();
        initChildName();
        initChildOccupation();
        if(childOccupationMap.size() < 1){
            return false;
        }
        childTrainInfoMap = ChildBussiness.getChildTrainInfoMap();
        if(childTrainInfoMap.size() < 1){
            return false;
        }
        initMinTrainType();
        childAppearanceList = new ChildDaoImpl().getChildAppearanceList();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    //双胞胎获取第一个孩子或者第二个孩子的性别
    public static int getChildSexByPosition(UserChildSite userChildSite,int position){
        if(position == 0)return userChildSite.getChildSex();
        int sex1=2,sex2=2;
        switch (userChildSite.getChildType()){
            case 1://男男
                sex1=1;sex2=1;break;
            case 2://男女
                sex1=1;sex2=2;break;
            case 3://女女
                sex1=2;sex2=2;break;
            case 4://女男
                sex1=2;sex2=1;break;
        }
        if(position == 1)return sex1;
        if(position == 2)return sex2;
        return userChildSite.getChildSex();
    }

    private void initChildOccupation() {
        Map<Integer, ChildOccupation> occupationMap = new ConcurrentHashMap<>();
        Map<Integer, List<ChildOccupation>> occupationTypeMap = new ConcurrentHashMap<>();
        ChildBussiness.getChildOccupationMap(occupationMap, occupationTypeMap);
        childOccupationMap = occupationMap;
        childOccupationTypeMap = occupationTypeMap;
    }

    private void initMinTalent() {
        int minTalent = Integer.MAX_VALUE;
        for(ChildTalentInfo childTalentInfo : childTalentInfoMap.values()){
            if(childTalentInfo.getId() < minTalent){
                minTalent = childTalentInfo.getId();
            }
        }
        minChildTalent = minTalent;
    }

    private void initMinTrainType() {
        int minTrain = Integer.MAX_VALUE;
        for(ChildTrainInfo childTrainInfo : childTrainInfoMap.values()){
            if(childTrainInfo.getTrainType() < minTrain){
                minTrain = childTrainInfo.getTrainType();
            }
        }
        minChildTrainType = minTrain;
        childTrainInfoList = new ArrayList<>(childTrainInfoMap.values());
        childTrainInfoList.sort(Comparator.comparingInt(ChildTrainInfo::getNeedTitle));
    }

    private void initChildName(){
        Map<String, List<String>> menMap = new ConcurrentHashMap<>();
        Map<String, List<String>> womenMap = new ConcurrentHashMap<>();
        List<ChildNameData> nameDataList = ChildBussiness.getChildNameDataList();
        for(ChildNameData nameData : nameDataList){
            if(!StringUtils.isNullOrEmpty(nameData.getMenName()) && !"0".equals(nameData.getMenName())){
                if(!menMap.containsKey(nameData.getLanguage())){
                    menMap.put(nameData.getLanguage(), new ArrayList<>());
                }
                menMap.get(nameData.getLanguage()).add(nameData.getMenName());
            }
            if(!StringUtils.isNullOrEmpty(nameData.getWomenName()) && !"0".equals(nameData.getWomenName())){
                if(!womenMap.containsKey(nameData.getLanguage())){
                    womenMap.put(nameData.getLanguage(), new ArrayList<>());
                }
                womenMap.get(nameData.getLanguage()).add(nameData.getWomenName());
            }
        }
        menNameMap = menMap;
        womenNameMap = womenMap;
    }

    public static boolean isSiteMax(int siteNum) {
        return siteNum >= GameConfig.CHILDREN_MAX_SITE_NUMBER;
    }

    public static ChildTalentInfo getChildTalentInfo(int childTalent) {
        return childTalentInfoMap.get(childTalent);
    }

    public static String getRandomChildName(int sex, String language){
        List<String> nameList;
        String randomName = "";
        if(eSexType.MALE.getValue() == sex){
            nameList = menNameMap.get(language);
            if(null == nameList){
                nameList = menNameMap.get(LanguageType.LANGUAGE_DEFAULT);
            }
        }else {
            nameList = womenNameMap.get(language);
            if(null == nameList){
                nameList = womenNameMap.get(LanguageType.LANGUAGE_DEFAULT);
            }
        }

        boolean isForbid;
        int loopTimes = 0;
        do {
            isForbid = false;
            if(null != nameList){
                int randomIndex = threadRandom.next(0, nameList.size());
                randomName = nameList.get(randomIndex);
            }
            if(!StringUtils.isNullOrEmpty(randomName)) {
                if (ForbiddenWordMgr.isNickNameForbidden(randomName)) {
                    isForbid = true;
                }
            }
            loopTimes++;
            if(loopTimes > 30){
                break;
            }
        }while (isForbid);
        return randomName;
    }

    public static int getRandomChildSex(int childCount){
        if(0 == childCount){
            return eSexType.FEMALE.getValue();
        }else if(1 == childCount){
            return eSexType.MALE.getValue();
        }
        int sex;
        int randomValue = threadRandom.next(0, 10);
        if (randomValue < 5) {
            sex = eSexType.FEMALE.getValue();
        } else {
            sex = eSexType.MALE.getValue();
        }
        return sex;
    }

    public static int getRandomChildOccupation(GamePlayer player){
        return ConfigMgr.getRandomChildOccupation((int) BeautyMgr.getTotalChildCount(player.getModule(BeautyModule.class).getBeautyMap()));
    }

    public static int getChildHeadIcon(int childSex){
        if(childSex == eSexType.FEMALE.getValue()){
            return 0;
        } else {
            return 1;
        }
    }

    public static Property getChildAdultReward(int childTalent, int occupation, boolean isLonely){
        ChildTalentInfo childTalentInfo = ChildMgr.getChildTalentInfo(childTalent);
        int itemCount = childTalentInfo.getAddItemCount();
        if(isLonely){
            itemCount = (int) Math.ceil(itemCount * ((double) GameConfig.CHILD_LONELY_ADULT_REWARD_ADDITION / 1000 + 1));
        }
        int itemId = ConfigMgr.getChildAdultRewardItemId(occupation);
        return new Property(itemId, BigInteger.valueOf(itemCount));
    }

    public static int getMinChildTalent() {
        return minChildTalent;
    }

    public static BigInteger getTrainCostSilver(int titleId, int trainType, int unlockSiteCount){
        TitleInfo titleInfo = TitleMgr.getTitleInfo(titleId - 1);
        ChildTrainInfo childTrainInfo = getChildTrainInfo(trainType);
        BigDecimal cost = new BigDecimal(titleInfo.getNeedEarnSpeed());
        cost = cost.multiply(BigDecimal.valueOf((double)childTrainInfo.getUnlockSiteCost(unlockSiteCount) / 1000)).setScale(0, BigDecimal.ROUND_UP);
        return cost.toBigInteger();
    }


    //第一版:3)子嗣赚钱=身份配置的子嗣赚钱*培养方式赚钱倍数/1000*天资赚钱系数/1000*职业赚钱系数/1000*（1+其他技能buff加成/1000）*（1+是否孤独终身系数/1000）
    //第二版:子嗣赚钱=身份配置的子嗣赚钱*培养方式赚钱倍数/1000*母亲的子嗣赚钱系数/1000*职业赚钱系数/1000*（1+其他技能buff加成/1000）*（1+是否孤独终身系数/1000）
    //第三版:
    public static BigInteger getChildAdultEarnSpeed(GamePlayer player, int trainType, int childTalent, int occupationType,
            int occupationAddition, int motherIntimacy, boolean isLonely, int childSex, MarriageInfo marriageInfo){
        int skillAddition = 0;
        int titleId = 10;      //npc子嗣赚速身份
        if(null != player){
            titleId = player.getTitleId();
            skillAddition = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType); //美名
            skillAddition += player.getModule(PatronsModule.class).getTalentSkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType); //天赋
            skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeedSexAddition.getValue(), childSex); //美名
            skillAddition += player.getModule(HouseModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType); //钱庄信誉等级技能
        }
        //身份配置的子嗣赚钱速度
        TitleInfo titleInfo = TitleMgr.getTitleInfo(titleId);
        ChildTrainInfo childTrainInfo = getChildTrainInfo(trainType);

        BigDecimal charitableAddition = new BigDecimal(player == null ? 0 : player.getModule(CharitableModule.class).getAddChildValue(occupationType));
        BigDecimal houseBankAddition = new BigDecimal(player == null ? 0 : player.getModule(HouseModule.class).getAddChildValue(occupationType));

        // 子嗣base赚钱系数2
        BigDecimal baseEarnSpeed = new BigDecimal(titleInfo.getChildBaseEarnSpeed2());
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}", baseEarnSpeed.toString());
        int motherIntimacyRatio = getMotherIntimacyRatio(motherIntimacy);
//        logger.info("ChildAdultEarnSpeed skillAddition:{},baseEarnSpeed:{},motherIntimacyRatio:{}", skillAddition, baseEarnSpeed.toString(),
//                motherIntimacyRatio);
        // 子嗣base赚钱系数2*母亲子嗣赚钱系数/1000
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(motherIntimacyRatio).divide(BigDecimal.valueOf(1000),
                CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));

        // 子嗣base赚钱系数2*母亲子嗣赚钱系数/1000 + 行善累技能效果加成
        baseEarnSpeed = baseEarnSpeed.add(charitableAddition);
        // 子嗣base赚钱系数加上钱庄技能加成
        baseEarnSpeed = baseEarnSpeed.add(houseBankAddition);

//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, motherIntimacyRatio:{}", baseEarnSpeed.toString(), motherIntimacyRatio);
        //*子嗣品质赚钱速度 /1000
        ChildTalentInfo childTalentInfo = getChildTalentInfo(childTalent);
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(childTalentInfo.getEarnSpeedAddition()).divide(BigDecimal.valueOf(1000),
                CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, talentAddition:{}", baseEarnSpeed.toString(), childTalentInfo.getEarnSpeedAddition());

        // * （1+培养方式加成/1000 + 职业加成/1000 + 美女美名加成/1000 + 门客天赋加成/1000）
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(1000 + childTrainInfo.getEarnSpeedAddition() + occupationAddition + skillAddition).
                divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, trainAddition:{}, occupationAddition:{}", baseEarnSpeed.toString(), childTrainInfo.getEarnSpeedAddition(), occupationAddition);
//        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(occupationAddition / 1000));

// * (1+所有美女美名对该子嗣加成效果/1000)
//        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(skillAddition / 1000 + 1));
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, skillAddition:{}", baseEarnSpeed.toString(), skillAddition);
        int lonelyAddition = 0;
        if(isLonely){
            lonelyAddition = ChildMgr.getChildLonelyEarnSpeedAddition(player, motherIntimacy);
            int curioAddition = (int) CurioMgr.getSkillAdditionBySkillType(eSkillType.ChildLonelyEarnSkill.getValue(), player, 0);
            if(curioAddition > 0){
                //要记录藏品的实际加成
                String curioAdd = baseEarnSpeed.multiply(BigDecimal.valueOf(1000 + curioAddition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toString();
                marriageInfo.setCurioAddition(curioAdd);
            }
            lonelyAddition += curioAddition;
            baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(1000 + lonelyAddition).divide(BigDecimal.valueOf(1000),
                    CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));
//            logger.info("ChildAdultEarnSpeed earnSpeed:{}, lonelyAddition:{}", baseEarnSpeed.toString(), lonelyAddition);
        }
//        logger.info("ChildAdultEarnSpeed skillAddition:{},baseEarnSpeed:{},motherIntimacyRatio:{},talentAddition:{},trainAddition:{},occupationAddition:{}," +
//                "lonelyAddition:{}", skillAddition, baseEarnSpeed.toString(),motherIntimacyRatio,childTalentInfo.getEarnSpeedAddition(),
//                childTrainInfo.getEarnSpeedAddition(), occupationAddition, lonelyAddition);
        baseEarnSpeed = baseEarnSpeed.add(new BigDecimal(titleInfo.getChildBaseEarnSpeed1()));
        return baseEarnSpeed.setScale(0, BigDecimal.ROUND_UP).toBigInteger();
    }

    public static int getChildOccupationAddition(int childOccupationId){
        ChildOccupation childOccupation = getChildOccupation(childOccupationId);
        return threadRandom.next(childOccupation.getMinParam(), childOccupation.getMaxParam() + 1);
    }

    public static boolean isLonely(long adultChildCount){
        if(adultChildCount < GameConfig.CHILD_LONELY_INDEX_PARAM){
            return false;
        }else if(adultChildCount == GameConfig.CHILD_LONELY_INDEX_PARAM){
            return true;
        }else {
            int randomValue = threadRandom.next(0, 1000);
            return GameConfig.CHILD_LONELY_PROBABILITY > randomValue;
        }
    }

    public static int getRandomOccupationId(int occupationType, int sex, boolean isLonely){
        if(childOccupationTypeMap.containsKey(occupationType)){
            List<ChildOccupation> dataList = new ArrayList<>();
            int totalWeight = 0;
            for(ChildOccupation data : childOccupationTypeMap.get(occupationType)){
                if(data.getSexLimit() == 0 || data.getSexLimit() == sex){
                    if(data.isLonely() == isLonely) {
                        dataList.add(data);
                        totalWeight += data.getWeight();
                    }
                }
            }
            if(dataList.size() > 0) {
                int randomValue = threadRandom.next(0, totalWeight);
                int tempWeight = 0;
                for(ChildOccupation childOccupation : dataList){
                    tempWeight += childOccupation.getWeight();
                    if (tempWeight >= randomValue) {
                        return childOccupation.getOccupationId();
                    }
                }
            }
        }
        return 0;
    }

    public static ChildTrainInfo getChildTrainInfo(int trainType){
        return childTrainInfoMap.get(trainType);
    }

    public static boolean canUseChildTrainType(int titleId, int trainType){
        ChildTrainInfo childTrainInfo = getChildTrainInfo(trainType);
        if(titleId < childTrainInfo.getNeedTitle()){
            return false;
        }
        int count = 0;
        for(int i = childTrainInfoList.size() - 1; i >=0; i--){
            ChildTrainInfo trainInfo = childTrainInfoList.get(i);
            if(trainInfo.getNeedTitle() <= titleId){
                count++;
            }
            if(count > 3){
                return false;
            }
            if(trainInfo.getTrainType() == trainType){
                break;
            }
        }
        return true;
    }

    public static ChildOccupation getChildOccupation(int occupationId){
        return childOccupationMap.get(occupationId);
    }

    public static int getMinChildTrainType() {
        return minChildTrainType;
    }

    /**
     * 子嗣培养增加阅历
     */
    public static long getTrainChildAddExp(GamePlayer player, ChildTalentInfo childTalent, UserChildSite userChildSite){
        int skillAddition = player.getModule(PatronsModule.class).getTalentSkillAddition(eSkillType.ChildTrainAddPatronsExp.getValue(), userChildSite.getChildOccupation());  //天赋
        skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExp.getValue(), userChildSite.getChildOccupation());  //美名
        skillAddition += CurioMgr.getSkillAdditionBySkillType(eSkillType.ChildTrainAddPatronsExp.getValue(), player, 0);
        skillAddition += CurioMgr.getSkillAdditionBySkillType(eSkillType.SpecialOccupationChildPatronsExpSkill.getValue(), player, userChildSite.getChildOccupation());
        if(0 == userChildSite.getChildType()) {
            skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExpSexAddition.getValue(), userChildSite.getChildSex());  //美名
        }else if(1 == userChildSite.getChildType()) {//男男
            skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExpSexAddition.getValue(), eSexType.MALE.getValue());  //美名
        }else if(3 == userChildSite.getChildType()){//女女
            skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExpSexAddition.getValue(), eSexType.FEMALE.getValue());  //美名
        }else {
            int tempAddition1 = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExpSexAddition.getValue(), eSexType.MALE.getValue());  //美名
            int tempAddition2 = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildTrainAddPatronsExpSexAddition.getValue(), eSexType.FEMALE.getValue());  //美名
            if(tempAddition1 > tempAddition2){//取大的加成值
                skillAddition += tempAddition1;  //美名
            }else {
                skillAddition += tempAddition2;
            }
        }
        //周卡特权加成
        skillAddition += player.getModule(CardModule.class).getChildTrainPatronsExpAddition();

        TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
        if(titleInfo.getChildTrainAddExp() <= 0){
            BigDecimal val1 = BigDecimal.valueOf(GameConfig.CHILD_TRAIN_DEFAULT_ADD_PATRONS_EXP).multiply(BigDecimal.valueOf(1000 + skillAddition)).
                    divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);

            if(userChildSite.isComprehend()){
                val1 = val1.multiply(BigDecimal.valueOf(GameConfig.CHILDREN_CHANGE_ICO_FAIRY_MULTIPLE)).multiply(BigDecimal.valueOf(GameConfig.CHILDREN_CHANGE_ICO_FAIRY_EXP_MULTIPLE))
                        .divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
            }
            return val1.longValue();
        }else {
            BigDecimal val1 = BigDecimal.valueOf(childTalent.getTrainAddPatronsExpParam() * titleInfo.getChildTrainAddExp()).
                    multiply(BigDecimal.valueOf(1000 + skillAddition)).divide(BigDecimal.valueOf(1000000), 0, BigDecimal.ROUND_UP);

            if(userChildSite.isComprehend()){
                val1 = val1.multiply(BigDecimal.valueOf(GameConfig.CHILDREN_CHANGE_ICO_FAIRY_MULTIPLE)).multiply(BigDecimal.valueOf(GameConfig.CHILDREN_CHANGE_ICO_FAIRY_EXP_MULTIPLE))
                        .divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
            }
            return val1.longValue();
        }
    }

    /**
     * 子嗣席位培养上限
     */
    public static int getChildSiteMaxTrainTimes(GamePlayer player){
        int times;
        TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
        times = titleInfo.getChildAddTrainTimes();
        if(0 == times){
            times = GameConfig.CHILDREN_MAX_TRAIN_TIMES;
        }
        times = times + player.getModule(CardModule.class).childSiteTrainAddTimes();
        times += CurioMgr.getSkillAdditionBySkillType(eSkillType.ChildEnergyLimitSkill.getValue(), player, 0);
        return times;
    }

    public static int getChildLonelyEarnSpeedAddition(GamePlayer player, int motherIntimacy){
        double v1 = (double) ConfigMgr.getChildLonelyEarnSpeedTitleEffect2() / 1000;
        double v2 = Math.pow(motherIntimacy, v1);
        double v3 = v2 * ConfigMgr.getChildLonelyEarnSpeedTitleEffect1();
        double skillAddition = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.LonelyEarnSpeedAddition.getValue(), 0);
        return BigDecimal.valueOf(v3 + skillAddition).setScale(0, BigDecimal.ROUND_UP).intValue();
    }

    /**
     * 子嗣培养赚速
     */
    public static BigInteger getChildGrowEarnSpeed(GamePlayer player, int trainType, int childTalent, int occupationType, int motherIntimacy,
            int childSex, int growAddition){
        if(growAddition <= 0){
            return BigInteger.ZERO;
        }
        int skillAddition;
        skillAddition = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType);       //美名
        skillAddition += player.getModule(PatronsModule.class).getTalentSkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType);       //天赋
        skillAddition += player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeedSexAddition.getValue(), childSex); //美名
        skillAddition += player.getModule(HouseModule.class).getIdentitySkillAddition(eSkillType.ChildEarnSpeed.getValue(), occupationType);       //美名

        //身份配置的子嗣赚钱速度
        TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
        ChildTrainInfo childTrainInfo = getChildTrainInfo(trainType);

        BigDecimal charitableAddition = new BigDecimal(player == null ? 0 : player.getModule(CharitableModule.class).getAddChildValue(occupationType));
        BigDecimal houseBankAddition = new BigDecimal(player == null ? 0 : player.getModule(HouseModule.class).getAddChildValue(occupationType));

        // 子嗣base赚钱系数2
        BigDecimal baseEarnSpeed = new BigDecimal(titleInfo.getChildBaseEarnSpeed2());
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}", baseEarnSpeed.toString());
        int motherIntimacyRatio = getMotherIntimacyRatio(motherIntimacy);
//        logger.info("ChildAdultEarnSpeed skillAddition:{},baseEarnSpeed:{},motherIntimacyRatio:{}", skillAddition, baseEarnSpeed.toString(),
//                motherIntimacyRatio);
        // *母亲子嗣赚钱系数/1000
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(motherIntimacyRatio).divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE,
                BigDecimal.ROUND_UP));

        // 子嗣base赚钱系数2*母亲子嗣赚钱系数/1000 + 行善累技能效果加成
        baseEarnSpeed = baseEarnSpeed.add(charitableAddition);
        // 子嗣base赚钱系数加上钱庄技能加成
        baseEarnSpeed = baseEarnSpeed.add(houseBankAddition);

//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, motherIntimacyRatio:{}", baseEarnSpeed.toString(), motherIntimacyRatio);
        //*子嗣品质赚钱速度 /1000
        ChildTalentInfo childTalentInfo = getChildTalentInfo(childTalent);
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(childTalentInfo.getEarnSpeedAddition()).divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE,
                BigDecimal.ROUND_UP));
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, talentAddition:{}", baseEarnSpeed.toString(), childTalentInfo.getEarnSpeedAddition());

        // * （1+培养方式加成/1000 + 美女美名加成/1000 + 门客天赋加成/1000）
        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(1000 + childTrainInfo.getEarnSpeedAddition() + skillAddition).
                divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));
//        logger.info("ChildAdultEarnSpeed earnSpeed:{}, trainAddition:{}, occupationAddition:{}", baseEarnSpeed.toString(), childTrainInfo.getEarnSpeedAddition(), occupationAddition);
//        baseEarnSpeed = baseEarnSpeed.multiply(BigDecimal.valueOf(occupationAddition / 1000));

//        logger.info("ChildAdultEarnSpeed skillAddition:{},baseEarnSpeed:{},motherIntimacyRatio:{},talentAddition:{},trainAddition:{},occupationAddition:{}," +
//                "lonelyAddition:{}", skillAddition, baseEarnSpeed.toString(),motherIntimacyRatio,childTalentInfo.getEarnSpeedAddition(),
//                childTrainInfo.getEarnSpeedAddition(), occupationAddition, lonelyAddition);
        baseEarnSpeed = baseEarnSpeed.add(new BigDecimal(titleInfo.getChildBaseEarnSpeed1())).multiply(BigDecimal.valueOf(growAddition).
                divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP));
        return baseEarnSpeed.setScale(0, BigDecimal.ROUND_UP).toBigInteger();
    }

    /**
     * 获取母亲亲密度加成
     */
    private static int getMotherIntimacyRatio(int motherIntimacy){
        //母亲亲密度加成x<=d:y=a/10000000*x~2+b/1000*x-1;x>d:y=a/1000000*d~2+b/1000*d+(x-d)c/1000-1
        int motherIntimacyRatio = 1000;
        try {
            List<Integer> motherIntimacyParams = StringUtils.stringToIntegerList(GameConfig.BEAUTY_CHILD_EARNSPEED_PARAM,"\\|");
            int a = motherIntimacyParams.get(0);
            int b = motherIntimacyParams.get(1);
            int c = motherIntimacyParams.get(2);
            int d = motherIntimacyParams.get(3);
            if(motherIntimacy <= d){
                motherIntimacyRatio = (BigDecimal.valueOf(a).multiply(BigDecimal.valueOf(motherIntimacy).multiply(BigDecimal.valueOf(motherIntimacy)))
                        .add(BigDecimal.valueOf(b).multiply(BigDecimal.valueOf(motherIntimacy).multiply(BigDecimal.valueOf(1000))))
                        .subtract(BigDecimal.ONE.multiply(BigDecimal.valueOf(1000000)))
                        .divide(BigDecimal.valueOf(1000000),0,BigDecimal.ROUND_DOWN)).intValue();
            }else{
                motherIntimacyRatio = (BigDecimal.valueOf(a).multiply(BigDecimal.valueOf(d).multiply(BigDecimal.valueOf(d)))
                        .add(BigDecimal.valueOf(b).multiply(BigDecimal.valueOf(d).multiply(BigDecimal.valueOf(1000))))
                        .add(BigDecimal.valueOf(motherIntimacy).subtract(BigDecimal.valueOf(d)).multiply(BigDecimal.valueOf(c)).multiply(BigDecimal.valueOf(1000)))
                        .subtract(BigDecimal.ONE.multiply(BigDecimal.valueOf(1000000)))
                        .divide(BigDecimal.valueOf(1000000),0,BigDecimal.ROUND_DOWN)).intValue();
            }
        }catch (Exception e){
            logger.error("母亲赚钱子嗣加成速度error:",e);
        }
        return motherIntimacyRatio;
    }

    /**
     * 获取子嗣成长阶段加成值
     */
    public static int getChildGrowStageAddition(int currentGrowth, int trainTimes, int onceAddGrowth){
        int addition = 0;
        List<ChildGrowStageAddition> stageAdditionList = ConfigMgr.getChildGrowStageAdditionList();
        int index = 0;
        int length = stageAdditionList.size();
        for(int i = 0; i < length; i++){
            ChildGrowStageAddition stageAddition = stageAdditionList.get(i);
            if(stageAddition.getGrowStage() > currentGrowth){
                index = i;
                break;
            }
        }
        ChildGrowStageAddition stageAddition = stageAdditionList.get(index);
        int growth = currentGrowth;
        for(int i = 0; i < trainTimes; i++){
            growth += onceAddGrowth;
            if(growth >= stageAddition.getGrowStage()){
                addition = stageAddition.getAddition();
                index++;
                if(index >= length){
                    break;
                }
                stageAddition = stageAdditionList.get(index);
            }
        }
        return addition;
    }

    /**
     * 获取子嗣成长增加赚速
     */
    public static BigInteger getGrowAddEarnSpeed(UserChildSite userChildSite, BigInteger growEarnSpeed, int position){
        BigInteger addEarnSpeed;
        if(2 == position) {
            addEarnSpeed = growEarnSpeed.subtract(userChildSite.getGrowAddEarnSpeed2());
        }else {
            addEarnSpeed = growEarnSpeed.subtract(userChildSite.getGrowAddEarnSpeed());
        }
        if(addEarnSpeed.compareTo(BigInteger.ZERO) < 0){
            addEarnSpeed = BigInteger.ZERO;
        }
        return addEarnSpeed;
    }

    public static int getGrandChildAppearanceId(int occupation, int sex) {
        List<Integer> list = new ArrayList<>();
        for (ChildAppearance appearance : childAppearanceList) {
            if (appearance.getOccupation() == occupation && appearance.getSex() == sex) {
                list.add(appearance.getId());
            }
        }
        if (list.size() > 0) {
            int index = threadRandom.next(list.size());
            return list.get(index);
        }
        return 0;
    }

    public static int getMaxTrainType(int titleId){
        int maxTrainType = 0;
        for(ChildTrainInfo c:childTrainInfoList){
            if(c.getNeedTitle() <= titleId && c.getTrainType() > maxTrainType){
                maxTrainType = c.getTrainType();
            }
        }
        return maxTrainType;
    }
}
